# coding=utf-8

"""

1. 在测试视频(OpenCV安装目录\sources\samples\data)上，使用基于混合高斯模型的背景提取算法，提取前景并显示(显示二值化图像，前景为白色)。
结果分析：
1) 测试视频（vtest.avi）共有 795 帧
2) 直接使用老师示范的程式码则噪声太多，所以利用上周所学的数学形态学去噪，效果很不错。
3) 每 100 帧截取一次前景并以二值化显示，左半侧是老师的程式码效果，右半侧是加上数学形态学滤波的对比
https://gitee.com/skyrookieyu/csdn_ai25_week3/blob/master/Comparison-100.jpg
https://gitee.com/skyrookieyu/csdn_ai25_week3/blob/master/Comparison-200.jpg
https://gitee.com/skyrookieyu/csdn_ai25_week3/blob/master/Comparison-300.jpg
https://gitee.com/skyrookieyu/csdn_ai25_week3/blob/master/Comparison-400.jpg
https://gitee.com/skyrookieyu/csdn_ai25_week3/blob/master/Comparison-500.jpg
https://gitee.com/skyrookieyu/csdn_ai25_week3/blob/master/Comparison-600.jpg
https://gitee.com/skyrookieyu/csdn_ai25_week3/blob/master/Comparison-700.jpg

"""

import cv2 as cv
import copy
import numpy as np

videoFilename = r'vtest.avi'  # 测试视频
cap = cv.VideoCapture()
cap.open(videoFilename)
if not cap.isOpened():
    print("Sorry, can't open video file - {}".format(videoFilename))
    exit(-1)
kernel = cv.getStructuringElement(cv.MORPH_CROSS, (3, 3))  # 用于形态学的的算子构建，第一个参数便是内核的形状（矩形，交叉形，椭圆形）
fgbg = cv.createBackgroundSubtractorMOG2()  # 实例化混合高斯模型
thresh = 200

frameCount = 0
while True:
    ret, frame = cap.read()
    if not ret:
        break

    frameCount += 1
    fgMask = fgbg.apply(frame)
    fgMask = cv.morphologyEx(fgMask, cv.MORPH_OPEN, kernel)  # 开运算，去噪
    #_, fgMask = cv.threshold(fgMask, 30, 0xff, cv.THRESH_BINARY)

    bgImage = fgbg.getBackgroundImage()

    _, cnts, _ = cv.findContours(fgMask.copy(), cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

    count = 0
    for c in cnts:
        area = cv.contourArea(c)
        if area < thresh:
            continue
        count += 1

        #x, y, w, h = cv.boundingRect(c)
        #cv.rectangle(frame, (x,y), (x+w, y+h), (0, 0xff, 0), 2)

    print('第 {} 帧共检测到 {} 个目标'.format(frameCount, count))
    cv.imshow('frame', frame)
    cv.imshow('background', bgImage)
    cv.imshow('foreground', fgMask)
    # if frameCount % 100 == 0:
        # cv.imwrite('{} - {}.jpg'.format("Ex", frameCount), fgMask)

    key = cv.waitKey(30)
    if key == 27:
        break

cap.release()
cv.destroyAllWindows()